package com.weatherstation.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.data.redis.RedisConnectionFailureException;

import java.util.concurrent.TimeUnit;

@Component
public class RedisTokenManager {

    private static final Logger logger = LoggerFactory.getLogger(RedisTokenManager.class);
    private static final String TOKEN_KEY_PREFIX = "token:";
    private static final long RENEWAL_THRESHOLD_MS = 30 * 60 * 1000; // 30分钟

    @Value("${jwt.expiration}")
    private Long jwtExpiration;

    private final StringRedisTemplate redisTemplate;
    private final JwtTokenUtil jwtTokenUtil;

    @Autowired
    public RedisTokenManager(StringRedisTemplate redisTemplate, JwtTokenUtil jwtTokenUtil) {
        this.redisTemplate = redisTemplate;
        this.jwtTokenUtil = jwtTokenUtil;
    }

    /**
     * 保存令牌到Redis
     * @param username 用户名
     * @param token JWT令牌
     */
    public void saveToken(String username, String token) {
        if (username == null || username.trim().isEmpty()) {
            logger.error("无法保存令牌：用户名为空");
            return;
        }
        
        if (token == null || token.trim().isEmpty()) {
            logger.error("无法保存令牌：令牌为空，用户: {}", username);
            return;
        }
        
        String key = getTokenKey(username);
        logger.info("保存令牌到Redis，用户: {}, 令牌前10位: {}", username, token.substring(0, Math.min(10, token.length())));
        
        try {
            redisTemplate.opsForValue().set(key, token, jwtExpiration, TimeUnit.MILLISECONDS);
            
            // 验证令牌是否成功保存
            String storedToken = redisTemplate.opsForValue().get(key);
            if (storedToken != null && storedToken.equals(token)) {
                logger.info("令牌成功保存到Redis，用户: {}", username);
            } else {
                logger.error("令牌保存到Redis失败，用户: {}, 存储的令牌: {}", username, storedToken);
            }
        } catch (RedisConnectionFailureException e) {
            logger.error("Redis连接失败，无法保存令牌，用户: {}", username, e);
        } catch (Exception e) {
            logger.error("保存令牌到Redis时发生错误，用户: {}", username, e);
        }
    }

    /**
     * 从Redis获取令牌
     * @param username 用户名
     * @return JWT令牌，如果不存在则返回null
     */
    public String getToken(String username) {
        if (username == null || username.trim().isEmpty()) {
            logger.error("无法获取令牌：用户名为空");
            return null;
        }
        
        String key = getTokenKey(username);
        String token = null;
        
        try {
            token = redisTemplate.opsForValue().get(key);
            if (token != null) {
                logger.debug("从Redis获取到令牌，用户: {}, 令牌前10位: {}", username, token.substring(0, Math.min(10, token.length())));
            } else {
                logger.warn("Redis中没有找到令牌，用户: {}", username);
            }
        } catch (RedisConnectionFailureException e) {
            logger.error("Redis连接失败，无法获取令牌，用户: {}", username, e);
        } catch (Exception e) {
            logger.error("从Redis获取令牌时发生错误，用户: {}", username, e);
        }
        
        return token;
    }

    /**
     * 删除Redis中的令牌
     * @param username 用户名
     */
    public void removeToken(String username) {
        if (username == null || username.trim().isEmpty()) {
            logger.error("无法删除令牌：用户名为空");
            return;
        }
        
        String key = getTokenKey(username);
        logger.info("从Redis删除令牌，用户: {}", username);
        
        try {
            Boolean result = redisTemplate.delete(key);
            if (Boolean.TRUE.equals(result)) {
                logger.info("令牌成功从Redis删除，用户: {}", username);
            } else {
                logger.warn("令牌删除失败或不存在，用户: {}", username);
            }
        } catch (RedisConnectionFailureException e) {
            logger.error("Redis连接失败，无法删除令牌，用户: {}", username, e);
        } catch (Exception e) {
            logger.error("从Redis删除令牌时发生错误，用户: {}", username, e);
        }
    }

    /**
     * 检查令牌是否需要续期，如果需要则生成新令牌
     * @param username 用户名
     * @param token 当前JWT令牌
     * @param userDetails 用户详情
     * @return 如果续期则返回新令牌，否则返回原令牌
     */
    public String checkAndRenewToken(String username, String token, org.springframework.security.core.userdetails.UserDetails userDetails) {
        if (username == null || username.trim().isEmpty() || token == null || token.trim().isEmpty()) {
            logger.error("无法检查令牌续期：用户名或令牌为空");
            return token;
        }
        
        try {
            long remainingTime = jwtTokenUtil.getTokenRemainingTimeMs(token);
            logger.debug("检查令牌是否需要续期，用户: {}，剩余时间: {} ms", username, remainingTime);
            
            // 如果剩余时间小于等于30分钟，则续期
            if (remainingTime <= RENEWAL_THRESHOLD_MS) {
                logger.info("令牌需要续期，用户: {}", username);
                String newToken = jwtTokenUtil.generateToken(userDetails);
                saveToken(username, newToken);
                return newToken;
            }
        } catch (Exception e) {
            logger.error("检查令牌续期时发生错误，用户: {}", username, e);
        }
        
        return token;
    }

    private String getTokenKey(String username) {
        return TOKEN_KEY_PREFIX + username;
    }
} 